﻿using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.EntityFramework;
using Microsoft.Owin.Security;
using Caltech.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Web;
using System.Web.Mvc;
using System.Security.Claims;
using CaltechSoft.Service.EntityFW.Entity;
using Caltech.Service.Common;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;

namespace Caltech.Controllers
{
    [Authorize]
    public class HomeController : Controller
    {
        public UserManager<User> UserManager { get; private set; }
        public RoleManager<Role> RoleManager { get; private set; }

        private IAuthenticationManager AuthenticationManager
        {
            get
            {
                return HttpContext.GetOwinContext().Authentication;
            }
        }

        public HomeController(UserManager<User> userManager, RoleManager<Role> roleManager)
        {
            UserManager = userManager;
            RoleManager = roleManager;
        }

        public async Task<ActionResult> Index()
        {
            var serializeSettings = new JsonSerializerSettings()
            {
                ContractResolver = new CamelCasePropertyNamesContractResolver()
            };

            var claims = ((ClaimsIdentity)User.Identity).Claims;
            var roleName = claims.FirstOrDefault(c => c.Type == ClaimTypes.Role).Value;
           // var roleName = Roles.Admin.ToString();

            ViewBag.UserName = User.Identity.GetUserName();
            ViewBag.RoleName = roleName;

            var user = UserManager.FindById(User.Identity.GetUserId());

            var areas = (await RoleManager.FindByNameAsync(roleName)).Areas;

            ViewBag.Account =  Newtonsoft.Json.JsonConvert.SerializeObject(new AccountInfoModel()
            {
                Username = user.UserName,
                FullName = user.FirstName + " " + user.LastName,
                Tel = user.Tel,
                Mobile = user.PhoneNumber,
                Email = user.Email,
                RoleName = roleName,
                Id = user.Id,
                Areas = areas
            }, serializeSettings);

            return View();
        }

        [AllowAnonymous]
        public ActionResult Register(string userType = null)
        {
            if (userType == "customer")
            {
                ViewBag.IsCustomer = true;
            }

            ViewBag.Title = "Register page";
            return View();
        }

        //
        // GET: /Account/Login
        [AllowAnonymous]
        public ActionResult Login(string returnUrl)
        {
            ViewBag.Title = "Logon page";
            ViewBag.ReturnUrl = returnUrl;
            return View();
        }

        //
        // POST: /Account/Login
        [HttpPost]
        [AllowAnonymous]
        public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
        {
            if (ModelState.IsValid)
            {
                var user = await UserManager.FindAsync(model.UserName, model.Password);

                if (user != null)
                {
                    if (user.LockoutEnabled)
                    {
                        ModelState.AddModelError("", "This user is locked");
                    }
                    else
                    {
                        await SignInAsync(user, model.RememberMe);
                        return RedirectToLocal(returnUrl);
                    }
                }
                else
                {
                    ModelState.AddModelError("", "Invalid username or password.");
                }
            }

            // If we got this far, something failed, redisplay form
            return View(model);
        }

        [AllowAnonymous]
        [HttpPost]
        public async Task<ActionResult> Register(RegisterBindingModel model)
        {
            if (!ModelState.IsValid)
            {
                return View(model);
            }

            User user = new User
            {
                UserName = model.UserName,
                Email = model.Email,
                FirstName = model.FirstName,
                LastName = model.LastName,
                PhoneNumber = model.Mobile,
                Tel = model.Phone
            };

            var result = await UserManager.CreateAsync(user, model.Password);

            if (!result.Succeeded)
            {
                ProcessErrorResult(result);
                return View(model);
            }

            var role = model.Role ?? Roles.Customer;

            result = await UserManager.AddToRoleAsync(user.Id, role.ToString());

            if (!result.Succeeded)
            {
                ProcessErrorResult(result);
            }

            ViewBag.Message = "Registration is successful";

            return View(model);
        }

        public ActionResult Logout()
        {
            AuthenticationManager.SignOut();
            return RedirectToAction("LogIn");
        }

        private async Task SignInAsync(User user, bool isPersistent)
        {
            AuthenticationManager.SignOut();
            var identity = await UserManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);
            AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent }, identity);
        }

        private ActionResult RedirectToLocal(string returnUrl)
        {
            if (Url.IsLocalUrl(returnUrl))
            {
                return Redirect(returnUrl);
            }
            else
            {
                return RedirectToAction("Index", "Home");
            }
        }

        private void ProcessErrorResult(IdentityResult result)
        {
            if (result == null)
            {
                ModelState.AddModelError("", "Result is null");
            }

            if (!result.Succeeded)
            {
                if (result.Errors != null)
                {
                    foreach (string error in result.Errors)
                    {
                        ModelState.AddModelError("", error);
                    }
                }
            }
        }
    }
}
